﻿/* License
 * This work is licensed under the Creative Commons Attribution 2.5 License
 * http://creativecommons.org/licenses/by/2.5/

 * You are free:
 *     to copy, distribute, display, and perform the work
 *     to make derivative works
 *     to make commercial use of the work
 * 
 * Under the following conditions:
 *     You must attribute the work in the manner specified by the author or licensor:
 *          - If you find this component useful a email to [sobne.cn@gmail.com] would be appreciated.
 *     For any reuse or distribution, you must make clear to others the license terms of this work.
 *     Any of these conditions can be waived if you get permission from the copyright holder.
 * 
 * Copyright sobne.cn All Rights Reserved.
*/
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Lib4Net.Expression;
using System.Data;
using System.Reflection;

namespace Lib4Net
{
    /// <summary>
    /// Extension方法
    /// </summary>
    public static class StaticExtension
    {
        /// <summary>
        /// 转化一个DataTable
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <returns></returns>
        public static DataTable ToDataTable<T>(this IEnumerable<T> list)
        {
            //创建属性的集合
            List<PropertyInfo> pList = new List<PropertyInfo>();
            //获得反射的入口
            Type type = typeof(T);
            DataTable dt = new DataTable();
            //把所有的public属性加入到集合 并添加DataTable的列
            Array.ForEach<PropertyInfo>(type.GetProperties(), p => { pList.Add(p); dt.Columns.Add(p.Name, p.PropertyType); });
            foreach (var item in list)
            {
                //创建一个DataRow实例
                DataRow row = dt.NewRow();
                //给row 赋值
                pList.ForEach(p => row[p.Name] = p.GetValue(item, null));
                //加入到DataTable
                dt.Rows.Add(row);
            }
            return dt;
        }
        /// <summary>
        /// DataTable 转换为List 集合
        /// </summary>
        /// <typeparam name="TResult">类型</typeparam>
        /// <param name="dt">DataTable</param>
        /// <returns></returns>
        public static List<T> ToList<T>(this DataTable dt) where T : class, new()
        {
            //创建一个属性的列表
            List<PropertyInfo> prlist = new List<PropertyInfo>();
            //获取TResult的类型实例  反射的入口
            Type t = typeof(T);
            //获得TResult 的所有的Public 属性 并找出TResult属性和DataTable的列名称相同的属性(PropertyInfo) 并加入到属性列表 
            Array.ForEach<PropertyInfo>(t.GetProperties(), p => { if (dt.Columns.IndexOf(p.Name) != -1) prlist.Add(p); });
            //创建返回的集合
            List<T> oblist = new List<T>();

            foreach (DataRow row in dt.Rows)
            {
                //创建TResult的实例
                T ob = new T();
                //找到对应的数据  并赋值
                prlist.ForEach(p => { if (row[p.Name] != DBNull.Value) p.SetValue(ob, row[p.Name], null); });
                //放入到返回的集合中.
                oblist.Add(ob);
            }
            return oblist;
        }
        /// <summary>
        /// 是否正确的E-Mail地址
        /// </summary>
        /// <param name="sEmail">需要检测的E-Mail地址串</param>
        /// <returns>boolen值</returns>
        public static bool IsValidEmailAddress(this string sEmail)
        {
            Regex regex = new Regex(RegularExpressions.EMAIL);
            return regex.Match(sEmail).Success;
        }
        /// <summary>
        /// 将字符串转换为list
        /// </summary>
        /// <typeparam name="T">List类型</typeparam>
        /// <param name="str">字符串</param>
        /// <param name="split">分隔符</param>
        /// <param name="convertHandler">类型转换</param>
        /// <returns>List</returns>
        public static List<T> ToList<T>(this string str, string split, Converter<string, T> convertHandler)
        {
            if (string.IsNullOrEmpty(str))
                return new List<T>();
            else
            {
                string[] arr = str.Split(new char[] { Convert.ToChar(split) });
                T[] Tarr = Array.ConvertAll(arr, convertHandler);
                return new List<T>(Tarr);
            }
        }
        #region int
        /// <summary>
        /// 检测输入字符串是否是有效的32位整数
        /// </summary>
        /// <param name="s">输入字符串</param>
        /// <returns>Boolen值</returns>
        public static bool IsInt(this string s)
        {
            int i;
            return int.TryParse(s, out i);
        }
        /// <summary>
        /// 将数字的字符串表示形式转换为它的等效 32 位有符号整数
        /// </summary>
        /// <param name="s">包含要转换的数字的字符串</param>
        /// <returns>与 s 中包含的数字等效的 32 位有符号整数</returns>
        public static int ToInt(this string s)
        {
            return int.Parse(s);
        }
        /// <summary>
        /// 将数字的字符串表示形式转换为它的等效 32 位有符号整数
        /// </summary>
        /// <param name="s">包含要转换的数字的字符串</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns></returns>
        public static int ToInt(this string s, int defaultValue)
        {
            if (s.IsInt())
                return int.Parse(s);
            else
                return defaultValue;
        }
        #endregion
        #region float
        /// <summary>
        /// 检测输入字符串是否是有效的32位浮点数
        /// </summary>
        /// <param name="s">输入字符串</param>
        /// <returns>Boolen值</returns>
        public static bool IsFloat(this string s)
        {
            float i;
            return float.TryParse(s, out i);
        }
        /// <summary>
        /// 将数字的字符串表示形式转换为它的等效单精度浮点数字
        /// </summary>
        /// <param name="s">包含要转换的数字的字符串</param>
        /// <returns>与 s 中指定的数值或符号等效的单精度浮点数字</returns>
        public static float ToFloat(this string s)
        {
            return float.Parse(s);
        }
        /// <summary>
        /// 将数字的字符串表示形式转换为它的等效单精度浮点数字
        /// </summary>
        /// <param name="s">包含要转换的数字的字符串</param>
        /// <param name="defaultValue">默认值</param>
        /// <returns></returns>
        public static float ToFloat(this string s, float defaultValue)
        {
            if (s.IsFloat())
                return s.ToFloat();
            else
                return defaultValue;
        }
        #endregion
        #region string
        /// <summary>
        /// 字符串是否为空
        /// </summary>
        /// <param name="s">需要检测的字符串</param>
        /// <returns>boolen值</returns>
        public static bool IsNullOrEmpty(this string s)
        {
            return string.IsNullOrEmpty(s);
        }
        #endregion

        #region Regex
        /// <summary>
        /// 指示所指定的正则表达式在指定的输入字符串中是否找到了匹配项。
        /// </summary>
        /// <param name="s">要搜索匹配项的字符串</param>
        /// <param name="pattern">要匹配的正则表达式模式</param>
        /// <returns>如果正则表达式找到匹配项，则为 true；否则，为 false</returns>
        public static bool IsMatch(this string s, string pattern)
        {
            return (s == null) ? false : Regex.IsMatch(s, pattern);
        }
        /// <summary>
        /// 在指定的输入字符串中搜索指定的正则表达式的第一个匹配项
        /// </summary>
        /// <param name="s">要搜索匹配项的字符串</param>
        /// <param name="pattern">要匹配的正则表达式模式</param>
        /// <returns>一个对象，包含有关匹配项的信息</returns>
        public static string Match(this string s, string pattern)
        {
            return (s == null) ? "" : Regex.Match(s, pattern).Value;
        }
        #endregion
    }
}
